/*
node文件的逻辑
每个node分成三个分片slice0,slice1,slice2,每个分片只和与自己平行的分片组成raft组，每个raft组有自己的ID，

整个流程：
client发来请求，coordinator将json转化为结构体然后封装，然后根据取模选择发送给哪个
*/
package node

import (
	"database/sql"
	raftt "distributed-database/raft"
	rpcc "distributed-database/rpcPackage"
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/rpc"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"sync"

	_ "modernc.org/sqlite"
)

// 分片结构
// 节点结构
// 提交用
type Node struct {
	NodeID int    `json:"node_id"` //节点id
	Status string `json:"status"`  //节点状态，activ
	mu     sync.RWMutex
	rafts  [3]*raftt.Raft // 三个分片对应的 Raft 实例
}
type Config struct {
	NodeID int `json:"node_id"`
}

const (
	chanNum = 10
)

// RPC服务结构
// StartNode creates a new node and initializes its Raft instances
func StartNode(nodeID int) *Node {
	//fmt.Printf("开始启动节点%d\n",nodeID)
	node := &Node{
		NodeID: nodeID,
		Status: "active",
		rafts:  [3]*raftt.Raft{}, // initialize array
	}
	fmt.Printf("节点 %d 开启\n", nodeID)

	// 初始化三个分片的 Raft 实例
	for i := range 1 {
		applyCh := make(chan raftt.ApplyMsg, chanNum)
		// 保存 Raft 实例
		node.rafts[i] = raftt.Make(3, nodeID, i, applyCh)
	}
	return node
}
func GetNodeId() int {
	data, err := os.ReadFile("config.json")
	if err != nil {
		log.Fatal(err)
	}

	var config Config
	if err := json.Unmarshal(data, &config); err != nil {
		log.Fatal(err)
	}
	return config.NodeID
}

// coordinator在自己端调用node的RPC函数
func (n *Node) RecvRequestToNode(args rpcc.CoordinatorRequest, reply *rpcc.CoordinatorReply) error {
	//reply.ReplyId, _ = strconv.Atoi(os.Args[1])
	// reply.handleOk=IsCurIdLeader(args.TargetId)
	// //如果不是leader则返回
	// if reply.handleOk==false{
	// 	return
	// }
	//如果是leader
	reply.Operation = args.Operation
	logvalue := raftt.LogValue{
		Data:      args.Data,
		Operation: args.Operation, // Removed because CoordinatorRequest has no Operation field
		Condition: args.Condition,
		TableName: args.TableName,
	}
	// 使用对应分片的 Raft 实例
	rf := n.rafts[args.TargetId]
	if rf == nil {
		return fmt.Errorf("raft instance not found for shard %d", args.TargetId)
	}
	if rf.State != 2 {
		reply.HandleOk = false
		return nil
	}

	fmt.Printf("节点 %d 收到请求，目标分片 %d，操作 %s,携带数据%v\n", n.NodeID, args.TargetId, args.Operation, args.Data)

	// 处理查询操作：不走 Raft 共识，直接查询自己的数据库
	if args.Operation == "query" {
		result, err := n.queryDatabase(args.TableName, args.Condition)
		if err != nil {
			reply.HandleOk = true
			reply.QuerySuccess = false
			fmt.Printf("节点 %d 查询失败: %v\n", n.NodeID, err)
			return nil
		}

		if result != nil {
			reply.HandleOk = true
			reply.QuerySuccess = true

			// 将结果转换为 JSON 再转为 map，确保 gob 能正确序列化
			resultJSON, err := json.Marshal(result)
			if err != nil {
				reply.QuerySuccess = false
				fmt.Printf("节点 %d 结果序列化失败: %v\n", n.NodeID, err)
				return nil
			}

			var resultData any
			err = json.Unmarshal(resultJSON, &resultData)
			if err != nil {
				reply.QuerySuccess = false
				fmt.Printf("节点 %d 结果反序列化失败: %v\n", n.NodeID, err)
				return nil
			}

			reply.Data = resultData // 只有查询操作才设置 Data 字段
			fmt.Printf("节点 %d 查询成功，返回数据: %v\n", n.NodeID, result)
			return nil
		} else {
			reply.HandleOk = true
			reply.QuerySuccess = false
			fmt.Printf("节点 %d 查询结果为空\n", n.NodeID)
			return nil
		}
	}

	// 处理写操作（insert, update, delete）：走 Raft 共识
	_, _, isLeader := rf.Start(logvalue)
	reply.HandleOk = isLeader

	switch args.Operation {
	case "insert":
		if isLeader {
			reply.InsertSuccess = true
			fmt.Printf("节点 %d INSERT 操作已提交到 Raft\n", n.NodeID)
		}
	/* case "update":
	if isLeader {
		reply.UpdateSuccess = true
		fmt.Printf("节点 %d UPDATE 操作已提交到 Raft\n", n.NodeID)
	}
	*/
	case "delete":
		if isLeader {
			reply.DeleteSuccess = true
			fmt.Printf("节点 %d DELETE 操作已提交到 Raft\n", n.NodeID)
		}
	}

	// 写操作不设置 reply.Data，只返回成功标志
	return nil
}

// AppendEntries is the node-level RPC handler used by other nodes to send
// AppendEntries requests. It dispatches the request to the correct per-shard
// Raft instance according to args.PieceNum.
func (n *Node) AppendEntries(args raftt.AppendEntriesArgs, reply *raftt.AppendEntriesReply) error {
	if args.PieceNum < 0 || args.PieceNum >= len(n.rafts) {
		return fmt.Errorf("不清楚具体的切片编号 %d", args.PieceNum)
	}
	rf := n.rafts[args.PieceNum]
	if rf == nil {
		return fmt.Errorf("raft实例没有找到 %d", args.PieceNum)
	}
	// Forward the RPC call to the appropriate Raft instance.
	rf.AppendEntries(args, reply)
	return nil
}
func (n *Node) RequestVote(args raftt.RequestVoteArgs, reply *raftt.RequestVoteReply) error {
	if args.PieceNum < 0 || args.PieceNum >= len(n.rafts) {
		return fmt.Errorf("不清楚具体的切片编号 %d", args.PieceNum)
	}
	rf := n.rafts[args.PieceNum]
	if rf == nil {
		return fmt.Errorf("raft实例没有找到 %d", args.PieceNum)
	}
	// Forward the RPC call to the appropriate Raft instance.
	rf.RequestVote(args, reply)
	return nil
}

// queryDatabase 查询数据库中符合条件的数据
// 直接查询本节点的数据库，不走 Raft 共识
func (n *Node) queryDatabase(tableName string, condition map[string]interface{}) (interface{}, error) {
	// 计算数据库文件路径
	cwd, _ := os.Getwd()
	dbfile := fmt.Sprintf("db%d.sqlite3", n.NodeID)
	candidates := []string{
		filepath.Join(cwd, dbfile),
		filepath.Join(cwd, "..", dbfile),
		filepath.Join(cwd, "..", "..", dbfile),
	}
	dbname := ""
	for _, p := range candidates {
		if _, err := os.Stat(p); err == nil {
			dbname = p
			break
		}
	}
	if dbname == "" {
		projectRoot := filepath.Clean(filepath.Join(cwd, "..", ".."))
		dbname = filepath.Join(projectRoot, dbfile)
	}

	// 打开数据库连接
	db, err := sql.Open("sqlite", dbname)
	if err != nil {
		return nil, fmt.Errorf("打开数据库失败: %w", err)
	}
	defer db.Close()

	// 构建 WHERE 子句
	// 注意：需要保证列名和参数顺序一致，避免 map 随机遍历导致的问题
	var whereClauses []string
	var values []any
	var cols []string

	// 先收集所有的列名，并排序以确保顺序一致
	for col := range condition {
		cols = append(cols, col)
	}

	// 按照字母顺序排序，确保顺序一致
	sort.Strings(cols)

	// 按照排序后的顺序构建 WHERE 子句和参数
	for _, col := range cols {
		whereClauses = append(whereClauses, fmt.Sprintf("%s = ?", col))
		values = append(values, condition[col])
	}

	var whereClause string
	if len(whereClauses) > 0 {
		whereClause = " WHERE " + strings.Join(whereClauses, " AND ")
	}

	// 构建 SELECT 查询（返回所有匹配行）
	query := fmt.Sprintf("SELECT * FROM %s%s", tableName, whereClause)

	// 执行查询
	rows, err := db.Query(query, values...)
	if err != nil {
		return nil, fmt.Errorf("查询失败: %w", err)
	}
	defer rows.Close()

	// 获取列名
	columns, err := rows.Columns()
	if err != nil {
		return nil, fmt.Errorf("获取列名失败: %w", err)
	}

	// 扫描所有结果
	var results []map[string]any
	for rows.Next() {
		values := make([]interface{}, len(columns))
		valuePtrs := make([]interface{}, len(columns))
		for i := range columns {
			valuePtrs[i] = &values[i]
		}
		if err := rows.Scan(valuePtrs...); err != nil {
			return nil, fmt.Errorf("扫描行失败: %w", err)
		}
		row := make(map[string]any)
		for i, col := range columns {
			val := values[i]
			if b, ok := val.([]byte); ok {
				row[col] = string(b)
			} else {
				row[col] = val
			}
		}
		results = append(results, row)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("遍历结果失败: %w", err)
	}
	if len(results) == 0 {
		fmt.Printf("节点 %d 从 %s 表中未找到符合条件的数据\n", n.NodeID, tableName)
		return nil, nil
	}
	fmt.Printf("节点 %d 从 %s 表中查询到 %d 条结果\n", n.NodeID, tableName, len(results))
	return results, nil
}

// 需要一个函数，接受来自其它节点的投票rpc请求，
func StartNodeRPCServer(node *Node, address string) {
	rpcServer := rpc.NewServer()
	err := rpcServer.RegisterName("node", node)
	if err != nil {
		log.Fatalf("StartNodeRPCServer: 注册 RPC 服务失败: %v", err)
	}

	listener, err := net.Listen("tcp", address)
	if err != nil {
		log.Fatalf("StartNodeRPCServer: 监听地址 %s 失败: %v", address, err)
	}
	log.Printf("StartNodeRPCServer: 节点 %d 的 RPC 服务器已启动，监听 %s", node.NodeID, address)

	go func() {
		for {
			conn, err := listener.Accept()
			if err != nil {
				log.Printf("StartNodeRPCServer: 接受连接失败: %v", err)
				continue
			}
			go rpcServer.ServeConn(conn)
		}
	}()

}

// 启动节点主函数
// func main() {
// 	// 注册所有要通过RPC传输的类型
// 	rpcc.RegisterTypes()
// 	// 节点配置
// 	nodeID, _ := strconv.Atoi(os.Args[1]) // 从命令行参数获取
// 	addr, _ := strconv.Atoi(os.Args[2])
// 	address := "localhost:" + strconv.Itoa(addr)
// 	// peerNodes := map[int]string{
// 	// 	0: "localhost:50051",
// 	// 	1: "localhost:50052",
// 	// 	2: "localhost:50053",
// 	// }
// 	var wg sync.WaitGroup
// 	wg.Add(7)
// 	defer wg.Done()
// 	// 启动节点
// 	node := StartNode(nodeID)

// 	// 启动RPC服务器
// 	StartNodeRPCServer(node, address)
// 	wg.Wait()
// }
